using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using Myotragus.Data.Domain;
using Myotragus.Data.Emit;
using Myotragus.Data.Metadata;
using Myotragus.Data.Tests.Utils;
using Myotragus.Data.Util;
using NUnit.Framework;

namespace Myotragus.Data.Tests.Tests.Emit
{
	[TestFixture]
	public class LoadEntityGeneratorFixture
	{
		[Test]
		public void CreateAnEntity()
		{
			var typ = new Mock<IDynamicType>();
			var asm = FixturesHelper.CreateAssemblyMock("Mocked.DynamicAssembly", typ);
			var map = FixturesHelper.CreateLocalizableMapping();

			var id = FixturesHelper.CreateId().Object;

			var generator = new LoadEntityGenerator(asm,
													FixturesHelper.CreateNameGenerator(), map.Object);

			var localizableProperties = ReflectionHelper.GetProperties(FixturesHelper.TypeOfTestEntity2)
				.Where(p => p.PropertyType == FixturesHelper.TypeOfString)
				.Select(p => new PropertyMapping { ColumnName = p.Name, Property = p })
				.Cast<IPropertyMapping>();

			var nonLocalizableProperties = ReflectionHelper.GetProperties(FixturesHelper.TypeOfTestEntity2)
				.Where(p => p.PropertyType != FixturesHelper.TypeOfString)
				.Select(p => new PropertyMapping { ColumnName = p.Name, Property = p })
				.Cast<IPropertyMapping>();

			map.Setup(m => m.GetLocalizableProperties(FixturesHelper.TypeOfTestEntity2))
				.Returns(localizableProperties);

			map.Setup(m => m.GetNonLocalizableProperties(FixturesHelper.TypeOfTestEntity2))
				.Returns(nonLocalizableProperties);

			map.Setup(m => m.GetPrimaryKey(FixturesHelper.TypeOfTestEntity2))
				.Returns(id);

			generator.GetImplementation(FixturesHelper.TypeOfTestEntity2);

			foreach (var property in nonLocalizableProperties)
				typ.Verify(m => m.DefineAutomaticProperty(property.PropertyName, property.PropertyType),
						   Times.Exactly(1));

			foreach (var property in localizableProperties)
				typ.Verify(m => m.DefineAutomaticProperty(property.PropertyName,
														  typeof(IList<LocalizableTextValue>)),
						   Times.Exactly(1));

			foreach (var property in ReflectionHelper.GetProperties(FixturesHelper.TypeOfTestEntity2))
				typ.Verify(m => m.DefineAutomaticProperty(property.Name, It.Is<Type>(x => true)),
						   Times.Exactly(1));
		}
	}
}